#pragma once

#include <MCF/Code/AbstractMessageThreadClass.hpp>
#include "CPUClass.hpp"
#include <set>
#include "GeneralDefinitions.hpp"

class WorkerThreadClass sealed : public MCF::AbstractMessageThreadClass {
private:
	static const UINT _UPDATE_GUI_INTERVAL = 500;
private:
	static bool _EventWorkerGetThreadIDProc(std::intptr_t nContext, std::intptr_t nArg1, std::intptr_t nArg2, std::intptr_t nArg3);

	static bool _EventCPUExceptionProc(std::intptr_t nContext, std::intptr_t nArg1, std::intptr_t nArg2, std::intptr_t nArg3);

	static void CALLBACK _UpdateGUITimerProc(HWND hWnd, UINT uMsg, UINT_PTR uTimerID, DWORD dwTime);
private:
	CPUClass _m_CPU;

	volatile bool _m_bSingleStep;
	volatile bool _m_bIsRunning;
	UINT_PTR _m_uUpdateTimerID;
public:
	WorkerThreadClass();
	virtual ~WorkerThreadClass();
protected:
	virtual void _PostCreate() override;
	virtual bool _DoOnIdle() override;
	virtual void _DoOnMessage(MSG *lpMsg) override;
private:
	void _OnSetIntPtr(std::intptr_t *lpnVar, std::intptr_t nNewValue);
	void _OnGetPhysicalDisks(std::set<int> *lpsetnDiskList);
	void _OnInitialize();
	void _OnLoadExternalData(DWORD *lpdwErrorCode, const WRKR_EXTERNALDATAPATHS *lpPaths);
	void _OnFirstRun();
	void _OnTrace();
	void _OnGo();

	void _BeginRunning();
	void _EndRunning();

	void _PerformCPUSingleStep();
	void _OnCPUException(DWORD dwErrorType, DWORD dwErrorAddr);
};
